Skip to content

feat(frontend): add cluster onboarding and dashboard design mock - #5849

Open
NicholasKissel wants to merge 1 commit into
mainfrom
feat/cluster-onboarding-mock
Open

NicholasKissel wants to merge 1 commit into
mainfrom
feat/cluster-onboarding-mock

Conversation

@NicholasKissel

@NicholasKissel NicholasKissel commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Interactive design mock (not wired to a backend) of the v3 cluster onboarding and cluster dashboard, rendered inside the real frontend shell so it picks up the dashboard theme in light and dark mode.

Try it: /mock/cluster-onboarding on the dev server (create page) or ?view=dashboard for a provisioned cluster. Ladle stories under cluster-onboarding/*.

Create page

  • Cloud first (AWS, GCP, Azure, Hetzner, BYOC), then region, plan, runners, name, allowed IPs; Aiven-style summary rail on the right with the monthly total.
  • Plan = control plane preconfigured by level (Free 1×R-5, Hobby 1×R-10, Team 3×R-20, Enterprise 3×R-40). Runners are sized manually: node size + node count, priced per node for the chosen cloud (Hetzner cheaper, BYOC billed by your cloud).

Dashboard

  • Overview: provisioning/running badge, "Connect your agent to Rivet" pill that copies a single setup prompt, connection information (external + internal endpoint, one admin token, S3-compatible object storage), deployment map, builds with which one is deployed.
  • Deployment map: public internet → control plane (object storage attached) → runners; every node shows provisioning/ready. New nodes added in Settings show up provisioning.
  • Logs: basic merged log stream.
  • Billing: control plane (fixed), runner compute, actor storage, object storage, egress; plan dialog and usage rows reuse the existing billing layout.
  • Settings: control plane (read-only), runner scaling, IP allowlist.

Pricing, node sizes, and provisioning timings are invented placeholders.

@railway-app

railway-app Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

🚅 Deployed to the rivet-pr-5849 environment in rivet-frontend

Service Status Web Updated
frontend-cloud 😴 Sleeping (View Logs) Web Oct 13, 2026 at 9:40 am UTC
kitchen-sink 😴 Sleeping (View Logs) Web Oct 13, 2026 at 3:26 am UTC
frontend-inspector 😴 Sleeping (View Logs) Web Oct 13, 2026 at 3:26 am UTC
ladle ✅ Success (View Logs) Web Oct 13, 2026 at 3:18 am UTC
website ❌ Build Failed (View Logs) Web Oct 13, 2026 at 3:16 am UTC
mcp-hub ✅ Success (View Logs) Web Oct 7, 2026 at 4:01 pm UTC

@the-company-company the-company-company Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 4 medium-severity findings

Reviewed commit c82ae4f.

Comment on lines +285 to +293
export const SETUP_PROMPT_URL = "https://rivet.dev/agent-setup/prompt.md";

/**
* The one line the user pastes into their agent. Everything else (skills,
* MCP server, CLI) lives in the file at SETUP_PROMPT_URL, like Cloudflare's
* agent-setup/prompt.md, so the dashboard never has to explain per-client
* install steps.
*/
export const SETUP_PROMPT = `Fetch and execute the appropriate instructions to set me up for Rivet from ${SETUP_PROMPT_URL}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Medium · The copied setup prompt points to a 404

The dashboard's primary “Connect your agent” action copies this string, but https://rivet.dev/agent-setup/prompt.md currently returns HTTP 404 and this PR does not add anything that publishes the setupPrompt() content below. An agent following the copied instruction therefore cannot perform any setup. Publish the prompt at this URL as part of the change, or have the button copy the generated instructions directly until that endpoint exists.

);
const [logs, setLogs] = useState<NamespaceLog[]>(() =>
actors
.flatMap((actor) =>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Medium · Namespace changes keep showing the previous namespace's logs

This state is initialized once from useCase and region; the namespace prop is used only in the export filename. Selecting another namespace therefore leaves the same actor history and live stream visible—even a newly created namespace whose table row says it has zero actors immediately shows production logs. Key or regenerate the mock log state by namespace (with empty data for a new namespace), so switching namespaces actually changes the isolated dataset.

Comment on lines +97 to +98
} = useLogScroll({
logs: visible,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Medium · Filtering can leave stale rows visible

useLogScroll intentionally freezes its input while follow is false and only accepts a replacement when the first entry changes. After scrolling up, a filter whose matches retain the same first row—or a filter with zero matches—therefore keeps rendering the old unfiltered displayedLogs, while the counter and export use the filtered visible array. Reset following/frozen state when the filter changes, or filter displayedLogs after the scroll hook so the rows, count, and export stay consistent.

Comment on lines +375 to +379
title="Cluster name"
description="Used in your endpoint hostname and in the dashboard."
>
<Input
{...form.register("name", { required: true })}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Medium · Cluster names can generate invalid endpoints

required accepts whitespace and arbitrary punctuation, but clusterEndpoints() later turns this value directly into a DNS label and S3 bucket. For example, !!! provisions successfully and displays https://---.us-east-1.rivet.run with bucket ---, while a whitespace-only name becomes an empty/invalid label. Validate the submitted name against the actual cluster/DNS naming rules (including nonempty normalized output and length) and show the validation error before provisioning.

@claude

claude Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review: cluster onboarding design mock

Well-scoped, self-contained mock. It sits outside the authed route tree, the pricing model has unit tests, and the production gating is sensible.

Should fix

  • frontend/.amp/portals/.proxies is a sandbox artifact (local proxy port and service name). Remove it and gitignore frontend/.amp/.
  • VITE_DEMO_ROUTE is build-time only. If it is set in a real production build, / redirects every visitor to the mock. Nothing enforces the "gitignored .env.local" comment, so consider a build warning.
  • mock.cluster-onboarding.tsx unhides the route for any truthy VITE_DEMO_ROUTE, even one pointing elsewhere. Compare against the mock path or use an explicit boolean.

Conventions (CLAUDE.md)

  • An em dash appears in the copied agent prompt in agent-connect.tsx. Use periods. (The placeholder dash in the summary is UI text and probably fine.)
  • A whole new panel set not available in every flavor is the case where CLAUDE.md asks for a features.* flag. Confirm with the user whether one is wanted. Verification was only done on a staging build, not OSS.
  • Forms (create flow, New namespace dialog, allowlist editor) should use react-hook-form. I found only 4 useForm references in the diff, so please check none hand-roll useState inputs.

Minor

  • Sharing allowedHosts between dev and vite preview is a good refactor.
  • Ladle now uses the real src/index.css. Please confirm existing stories still render in both themes.
  • Make sure nothing in catalog.ts looks like a real credential (admin tokens shown are fake).

Tests
model.test.ts covers the pricing and quote model. UI is untested, which is acceptable for a mock.

@claude

claude Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review: v3 cluster onboarding design mock

Overall this is a self-contained mock. It sits under /mock/*, outside the authed tree, and has unit tests for the pricing model (model.test.ts). I read the shared and infra changes (__root.tsx, vite.config.ts, .gitignore, .ladle/*, mock routes) closely. I only skimmed the component bodies, and I did not run the app or the tests.

Issues worth addressing

  1. Demo redirect in __root.tsx. VITE_DEMO_ROUTE redirects / for every flavor, and it is a build-time flag. Nothing enforces that it is unset in production builds. Consider also requiring !features.auth. Also check the OSS /ui/ base, where the pathname may not be exactly /.
  2. Feature flag. Per CLAUDE.md, a whole new panel should be behind a features.* flag, or the PR should say the mock is deliberately exempt. Confirm the mock is lazy-loaded and not in the main bundle for the OSS and cloud flavors.
  3. Form state. CLAUDE.md requires react-hook-form for user-submitted form state. The create page uses it. ip-allowlist.tsx, runners-config.tsx and the settings editors use plain useState. If they accept input, move them to RHF.
  4. Unrelated changes bundled in. The .amp/ gitignore entry and the allowedHosts refactor (plus preview.allowedHosts) in vite.config.ts are sandbox tooling and belong in a separate change.
  5. .ladle/ladle.css rewrite. It drops the forced dark theme and theme import, which affects every existing Ladle story. Please verify the other stories still render.
  6. mock.cluster-map-lab is a dev harness but ships in demo builds. Gate it on DEV only.

Style

  • Avoid em dashes in prose and UI copy (CLAUDE.md), for example "Copied. Paste it into your agent — it sets up Rivet…" in agent-connect.tsx.
  • Make sure timers and animation frames in cluster-map-lab.tsx and deployment-map.tsx are cleaned up on unmount.

Tests
model.test.ts is good. There is no coverage of the beforeLoad guards (demo redirect and notFound), and a small test would protect the production 404 behavior.

Security
This is frontend only. Make sure the admin token and S3 credentials shown in the connection panel are obviously fake strings.

Nothing blocking. Items 1, 2 and 5 are the ones I would resolve before merging.

🤖 Generated with Claude Code

@NicholasKissel
NicholasKissel force-pushed the feat/cluster-onboarding-mock branch from 7bb99e8 to 092bb7f Compare October 9, 2026 20:49
@NicholasKissel
NicholasKissel force-pushed the feat/cluster-onboarding-mock branch from 092bb7f to 52a1175 Compare October 9, 2026 21:10
@NicholasKissel
NicholasKissel force-pushed the feat/cluster-onboarding-mock branch from 52a1175 to 38390df Compare October 9, 2026 21:24
@NicholasKissel
NicholasKissel force-pushed the feat/cluster-onboarding-mock branch from 38390df to 145f9fa Compare October 9, 2026 22:26
@NicholasKissel
NicholasKissel force-pushed the feat/cluster-onboarding-mock branch from 145f9fa to 3427ef3 Compare October 9, 2026 22:34
@NicholasKissel
NicholasKissel force-pushed the feat/cluster-onboarding-mock branch from 3427ef3 to 6ab0d69 Compare October 9, 2026 22:56
@NicholasKissel
NicholasKissel force-pushed the feat/cluster-onboarding-mock branch from 6ab0d69 to 46da0e0 Compare October 9, 2026 23:17
@NicholasKissel
NicholasKissel force-pushed the feat/cluster-onboarding-mock branch from 46da0e0 to fe70ac3 Compare October 9, 2026 23:30
@NicholasKissel
NicholasKissel force-pushed the feat/cluster-onboarding-mock branch from fe70ac3 to 2e5fc42 Compare October 9, 2026 23:38
@claude

claude Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Review: cluster onboarding and dashboard design mock

This is a non-wired design mock, so my feedback is mostly about keeping it contained. I reviewed the PR metadata and a grep of the added lines. I couldn't read the full diff, so the points below are from that grep and not a line-by-line read.

Things to check

  • Production exposure: Confirm /mock/cluster-onboarding and /mock/cluster-map-lab are not reachable in production or cloud builds. Gate them on import.meta.env.DEV, or put them behind a flag in frontend/src/lib/features.ts as CLAUDE.md describes. The invented pricing and provisioning copy shouldn't ship to real users.
  • Root and Vite changes: I couldn't read the __root.tsx and vite.config.ts changes. Check that the mock shell and Ladle setup don't alter normal routing or build output. routeTree.gen.ts is generated, so regenerate it and don't edit it by hand.
  • Flavor testing: CLAUDE.md asks for visual changes to be checked in OSS and cloud flavors. Say in the PR whether you did that.

Conventions

  • Forms: create-cluster-page.tsx and ip-allowlist.tsx use react-hook-form, which matches the convention. runners-config.tsx and the settings panels hold values in useState (runnerCount, selection, filter). If any of those are user-submitted form inputs, they should go through RHF too. The log filter is probably fine as plain state.
  • Dashes: The comment rule bans em dashes in prose. The user-facing copy has some (for example Paste it into your agent — it sets up Rivet). In UI strings it's a minor point, but check code comments for the same.
  • Tests: model.test.ts and scene.test.ts cover the pricing model and scene logic, which is good. If any vi.waitFor calls were added, they need the adjacent justification comment.

Code quality

  • cluster-dashboard-page.tsx holds many independent useState hooks (view, deployed build, rollouts, engine version, pending). Consider a useReducer or extracting sub-components if the mock grows.
  • scene.ts and cluster-map-lab.tsx use timers and a useSyncExternalStore scene. Verify that intervals, animation frames and subscriptions are cleaned up on unmount.

Security and performance: No concerns. This is mock data with no backend calls. The admin token and endpoints shown must be hard-coded fake values, so make sure none of them look like real credentials.

Overall this is reasonable for a mock. The main ask is to gate the routes out of production builds.

@claude

claude Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Review: cluster onboarding design mock

Overall this is a well-scoped mock. It's gated to dev and demo builds, it uses react-hook-form as CLAUDE.md requires, and it has unit tests for model.ts and scene.ts. I only read the routing, config and gating files plus a grep of the diff. I did not read the ~7k lines of component code in detail.

Issues and suggestions

  1. Mock routes stay in the production bundle. The notFound() guard in mock.cluster-onboarding.tsx and mock.cluster-map-lab.tsx is a runtime check, so the mock UI and catalog.ts are still bundled and the generated route tree references them. If production should never carry them, lazy-load the components so they split into a chunk fetched only on those routes. That also keeps invented pricing out of the main bundle.
  2. VITE_DEMO_ROUTE is a build-time footgun. It redirects / in __root.tsx and unlocks both mock routes, which sit outside the authed tree. Nothing stops it leaking into a real build via a stray .env.local or CI env. Consider failing the build when it is set with a production flavor, or document it in .claude/reference/feature-flags.md.
  3. Feature-flag convention. CLAUDE.md says a whole new page or subsystem should ship behind a flag in features.ts. The env gate may be deliberate for a mock; please confirm. If the real v3 cluster UI builds on these components later, it will need a flag.
  4. Redirect only matches an exact /. location.pathname === "/" may miss the /ui/ base used when multitenancy is off. Check the demo redirect in the OSS flavor, or handle the base path.
  5. Unrelated scope. The vite.config.ts allowedHosts refactor (plus preview.allowedHosts) and the .ladle/ladle.css change (-44 lines) are infrastructure changes. Splitting them out would keep the revision self-contained.
  6. routeTree.gen.ts is generated. Confirm it was regenerated by the router plugin and not hand-edited.
  7. Test coverage. The pure logic (model, scene) is covered. actor-logs.ts (341 lines) and the form flows have no tests, which is acceptable for a mock.
  8. Visual verification. CLAUDE.md asks for checks in OSS and cloud flavors and in light and dark mode. The PR description doesn't mention OSS verification, so please confirm it.

Nits

  • The allowedHosts comment mentions "Amp orbs" and sandbox hostnames. Environment-specific comments like that age badly.
  • Placeholder pricing is hard-coded in catalog.ts. A short note that the values are invented would keep them from being mistaken for real prices.

No security or performance blockers for a dev and demo-only mock. Items 1, 2 and 4 are the ones I'd address before merge.

@claude

claude Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Review

Frontend-only design mock, so risk is low. It uses react-hook-form for the create form and the allowlist input, and the mock routes are gated behind DEV or VITE_DEMO_ROUTE. I only skimmed the diff and ran nothing (no build, tests, or browser check), so the notes below are from reading it.

Worth addressing

  • Demo-build gating (__root.tsx, mock.*.tsx). VITE_DEMO_ROUTE is a build-time flag that both unlocks the mock routes and redirects / away from the login flow. If it leaks into a real deploy's env, production silently loses its entry point. Consider a build-time guard that fails if it's set together with the auth/platform flags. At minimum, document it next to features.ts instead of only in a comment in __root.tsx.
  • Feature flags. CLAUDE.md asks that significant new panels sit behind a flag in frontend/src/lib/features.ts. The routes are env-gated, which is reasonable for a mock. Please confirm that is the intended approach rather than a flag. Also check the OSS and cloud flavors, since the mock sits outside the _context tree.
  • useState for non-form state. Local UI state like copied, plansOpen and rollouts is fine. selection in the flow (useState(initial)) mirrors form data. Since the create page already uses RHF, keep a single source of truth to avoid drift.
  • Unrelated change in vite.config.ts. Hoisting allowedHosts out of server is a refactor that isn't part of this feature. Consider splitting it into its own revision.
  • Wording. The agent-connect copy and a few comments contain em dashes (e.g. "Copied. Paste it into your agent — it sets up Rivet..."). CLAUDE.md says to avoid them in prose and comments.
  • Secrets in the mock. DiscreteInput shows an admin token and S3 secret key. Make sure these are obvious fakes (e.g. mock_...) so secret scanners and readers don't mistake them for real credentials.

Tests

  • model.test.ts and scene.test.ts cover pricing and scene logic with no mocking, which is good. There is no coverage for the create-form flow, which is acceptable for a mock.

Nits

  • routeTree.gen.ts is regenerated. Make sure it matches the router plugin output.
  • The new .ladle/ config adds Ladle tooling. Confirm the dependency is declared in package.json and that CI doesn't try to build it.
  • Hardcoded placeholder pricing should stay clearly labelled as invented. The PR description already says so, and a short comment in catalog.ts would help.

Overall this looks reasonable as a mock. The main ask is a safer story for VITE_DEMO_ROUTE.

@claude

claude Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Review

Large, self-contained design mock, mostly isolated under components/cluster-onboarding/ and /mock/* routes. Nothing blocking. Notes below.

Things to address

  • Production exposure of mock routes. mock.cluster-onboarding.tsx 404s only when !DEV && !VITE_DEMO_ROUTE. That is fine, but the mock code and routeTree.gen.ts entries still ship in the prod bundle (the route is lazy only if code-split). Please confirm the chunk is not loaded on normal routes. mock.cluster-map-lab.tsx should get the same guard if it does not have it.
  • __root.tsx redirect. The VITE_DEMO_ROUTE redirect on / runs in every flavor. Make sure it is a strict no-op when the env var is unset, and consider also gating on a flag per the Frontend Feature Flags guidance, or at least confirm OSS and cloud flavors were checked.
  • vite.config.ts. __VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS adds arbitrary allowed hosts, and the comment mentions a vendor-specific sandbox ("Amp orbs"). This is unrelated to the mock and widens dev-server host checks; it is better in a separate PR, with a more generic comment.
  • Form state convention. CLAUDE.md requires react-hook-form for user-submitted form state. The create page and one other file use it, but several places hand-roll controlled state with useState (runners-config.tsx selection and node counts, ip-allowlist.tsx/settings inputs, logs-panel filter, and the billing/plan dialog). The log filter is not a submitted form, so that is fine, but the runner-scaling and IP-allowlist settings inputs should likely use RHF.
  • Style: em dash. The copied agent prompt text in agent-connect.tsx ("Copied. Paste it into your agent — it sets up Rivet…") and the "—" placeholder in the summary use em dashes. CLAUDE.md bans em dashes in plain-English prose. The "—" empty-value glyph in UI is arguably fine, but the prose should change.

Minor

  • .ladle/ladle.css drops about 44 lines and .ladle/components.tsx/config.mjs change. Please confirm that existing stories still render the theme correctly.
  • catalog.ts (990 lines) and product-content.ts (563 lines) are invented pricing and copy. They are clearly labeled as placeholders in the PR body, but a header comment in those files saying "mock data, not real pricing" would help avoid it leaking into the real UI.
  • dashboard state such as onboarded, rollouts, and deployedBuildId is all local useState. That is fine for a mock, but it will be thrown away when this is wired up.

Tests

model.test.ts and scene.test.ts cover the pricing model and the deployment scene logic, which is good coverage for a mock. I did not run them locally.

Security

No auth, secrets, or network calls are introduced. The "admin token" and endpoints shown are fake. The only item is the dev-server host allowlist noted above.

This branch had an error being deployed

1 failed deployment
rivet-frontend / rivet-pr-5849 — 9c796d8e Deployed Oct 13, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant